﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

using VistaDB;
using VistaDB.DDA;

namespace CodePlex.VistaDB {
    public partial class Library {

        private string NetException = "Network Exception: ";
        private string VdbException = "VistaDB Exception: ";

            // Open the database with the paramaeters supplied from the constructor
            static public IVistaDBDatabase GetDatabase(string DatabaseFileName, string Password, VistaDBDatabaseOpenMode DatabaseOpenMode) 
            {
                if (!File.Exists(DatabaseFileName)) throw new System.IO.FileNotFoundException();

                IVistaDBDatabase db = VistaDBEngine.Connections.OpenDDA().OpenDatabase(DatabaseFileName, DatabaseOpenMode, Password);
                return db;
            }

            static public void CloseDatabase(IVistaDBDatabase db) 
            {
                if ((db != null) && (!db.IsClosed)) 
                {
                    db.Close();
                    db.Dispose();
                    db = null;
                }
            }

        public class Schema {

            public void ExportDBSchema(string ExportFilename, IVistaDBDatabase db) {
                sVDatabaseSchema dbSchema = GetDatabaseLevelSchema(db);
                System.Text.StringBuilder sb = new StringBuilder();
                sb.Append("Database:\t" + dbSchema.Filename + "\r");
                sb.Append("Assemby Count:\t" + dbSchema.Assemblies.Count.ToString() + "\r");
                sb.Append("Case Sensitive:\t" + dbSchema.CaseSensitive.ToString() + "\r");
                sb.Append("CLR Procs Count:\t" + dbSchema.CLRProcs.Count.ToString() + "\r");
                sb.Append("CLR Triggers Count:\t" + dbSchema.CLRTriggers.Count.ToString() + "\r");
                // sb.Append("Constraints Count:\t" + dbSchema.Constraints.Count.ToString() + "\r");
                sb.Append("Culture:\t" + dbSchema.Culture + "\r");
                sb.Append("Description:\t" + dbSchema.Description + "\r");
                sb.Append("PageSize:\t" + dbSchema.PageSize.ToString() + "\r");
                sb.Append("\r");
                sb.Append("\r");
                string description = dbSchema.Description;

                foreach (sVTableSchema ts in dbSchema.TableSchemas) {
                    sb.Append("Table Name:\t" + ts.Name + "\r");
                    sb.Append("\tDescription:\t" + ts.Description + "\r");
                    sb.Append("\tColumns: (" + ts.Columns.Count.ToString() + ")\r");
                    sb.Append("\t\tRow Index\tName\tVDB Type\tLength\tType\tDescription\tNullable\tCaption\tEncrypted\tMinimum\tMaximum\r");
                    foreach (sVColumnSchema cs in ts.Columns) {
                        sb.Append("\t\t" + cs.RowIndex.ToString());
                        sb.Append("\t" + cs.Name);
                        sb.Append("\t" + cs.VDBType.ToString());
                        sb.Append("\t" + cs.MaxLength.ToString());
                        sb.Append("\t" + cs.SystemType.ToString().Replace("System.", ""));
                        sb.Append("\t" + cs.Description);
                        sb.Append("\t" + cs.AllowNull.ToString());
                        sb.Append("\t" + cs.Caption);
                        sb.Append("\t" + cs.Encrypted.ToString());
                        // sb.Append("\t"); if (cs.MinValue != null) sb.Append(cs.MinValue.ToString());
                        // sb.Append("\t"); if (cs.MaxValue != null) sb.Append(cs.MaxValue.ToString());
                        sb.Append("\r");
                    }
                    sb.Append("\tIdentity Columns: (" + ts.Identities.Count.ToString() + ")\r");
                    if (ts.Identities.Count > 0) {
                        sb.Append("\tColumnName\tSeed Value\tStep\tDescription\r");
                        foreach (sVTableIdentity ti in ts.Identities) {
                            sb.Append("\t\t" + ti.ColumnName);
                            sb.Append("\t" + ti.SeedValue);
                            sb.Append("\t" + ti.StepExpression);
                            sb.Append("\t" + ti.Description);
                            sb.Append("\r");
                        }
                        sb.Append("\tIndexes: (" + ts.Indexes.Count.ToString() + ")\r");
                        sb.Append("\tTriggers: (" + ts.Triggers.Count.ToString() + ")\r");
                        sb.Append("\r");
                    }
                }
                System.IO.File.WriteAllText(ExportFilename, sb.ToString());
            }

            public sVDatabaseSchema GetDatabaseLevelSchema(IVistaDBDatabase db) {
                    

                sVDatabaseSchema sdb = new sVDatabaseSchema();
                sdb.CaseSensitive = db.CaseSensitive;
                sdb.Culture = db.Culture.Name;
                sdb.Description = db.Description;
                sdb.Assemblies = db.EnumAssemblies();
                sdb.CLRProcs = db.EnumCLRProcs();
                sdb.CLRTriggers = db.EnumCLRTriggers();

                // Open the table exclusive or shared based on the method parameter
                sdb.TableSchemas = new List<sVTableSchema>();
                ArrayList tables = new ArrayList();
                tables = db.EnumTables();
                foreach (string tablename in tables) {
                    sVTableSchema ts = new sVTableSchema();
                    IVistaDBTableSchema vts = db.TableSchema(tablename);
                    ts.ColumnCount = vts.ColumnCount;
                    ts.Description = vts.Description;
                    ts.Name = vts.Name;

                    // Process Columns
                    ts.Columns = new List<sVColumnSchema>();
                    foreach (IVistaDBColumnAttributes colInfo in vts) {
                        sVColumnSchema cs = new sVColumnSchema();
                        cs.AllowNull = colInfo.AllowNull;
                        cs.Caption = colInfo.Caption;
                        cs.CodePage = colInfo.CodePage;
                        cs.Description = colInfo.Description;
                        cs.Encrypted = colInfo.Encrypted;
                        cs.ExtendedType = colInfo.ExtendedType;
                        cs.FixedType = colInfo.FixedType;
                        cs.MaxLength = colInfo.MaxLength;
                        cs.MaxValue = colInfo.MaxValue;
                        cs.MinValue = colInfo.MinValue;
                        cs.Name = colInfo.Name;
                        cs.Packed = colInfo.Packed;
                        cs.ReadOnly = colInfo.ReadOnly;
                        cs.RowIndex = colInfo.RowIndex;
                        cs.SystemType = colInfo.SystemType;
                        cs.UniqueID = colInfo.UniqueId;
                        cs.VDBType = colInfo.Type;
                        ts.Columns.Add(cs);
                    }

                    // Process Identities
                    ts.Identities = new List<sVTableIdentity>();
                    foreach (IVistaDBIdentityInformation ii in vts.Identities) {
                        sVTableIdentity sti = new sVTableIdentity();
                        sti.ColumnName = ii.ColumnName;
                        sti.Description = ii.Description;
                        sti.Name = ii.Name;
                        sti.SeedValue = int.Parse(ii.SeedValue);
                        sti.StepExpression = int.Parse(ii.StepExpression);
                        ts.Identities.Add(sti);
                    }

                    // Process Indexes
                    ts.Indexes = new List<sVTableIndex>();
                    foreach (IVistaDBIndexInformation ivi in vts.Indexes) {
                        // Only add indexes for this table
                        sVTableIndex sti = new sVTableIndex();
                        sti.Description = ivi.Description;
                        sti.FKConstraint = ivi.FKConstraint;
                        sti.ForExpression = ivi.ForExpression;
                        sti.FTS = ivi.FTS;
                        sti.KeyExpression = ivi.KeyExpression; //string
                        // ivi.KeyStructure
                        sti.Name = ivi.Name;
                        sti.Primary = ivi.Primary; //bool
                        sti.Temporary = ivi.Temporary; //bool
                        sti.Unique = ivi.Unique; // bool
                        sti.VIndex = ivi.VIndex; // bool
                        ts.Indexes.Add(sti);
                    }


                    // Process Triggers
                    ts.Triggers = new List<sVTableTrigger>();
                    foreach (IVistaDBCLRTrigger ivt in vts.Triggers) {
                        // Only add triggers for this table
                        if (string.Compare(ivt.TableName, tablename, true) == 0) {
                            sVTableTrigger sti = new sVTableTrigger();
                            sti.AssemblyName = ivt.AssemblyName;
                            sti.Description = ivt.Description;
                            sti.FullHostedName = ivt.FullHostedName;
                            sti.Name = ivt.Name;
                            sti.Signature = ivt.Signature;
                            sti.Action = ivt.TriggerAction;
                            ts.Triggers.Add(sti);
                        }
                    }
                    sdb.TableSchemas.Add(ts);
                }
                return sdb;
            }
        }
    }
}